import { _decorator, Component, instantiate, Node, Prefab, Sprite, tween, Vec3 } from 'cc';
import { Ball } from './Ball';
import { TubePart } from './TubePart';
import { BallColor, TubePartType } from './Enums';
import { GameManager } from './GameManager';
import { getNewParentLocalPosInChild, setParentWithoutChangingWorldPos } from './Tool';
const { ccclass, property } = _decorator;

@ccclass('Tube')
export class Tube extends Component {
    @property
    capacity: number = 4; // 最大容量（含木塞）

    @property(Node)
    node: Node = null; // 试管根节点
    @property(Sprite)
    corkSprite: Sprite = null; // 木塞图（默认隐藏）
    @property(Node)
    topNode: Node = null; // 顶部节点
    @property(Node)
    middleNode: Node = null; // 中间部分的父节点

    @property(Prefab)
    effectPrefab: Prefab = null; // 特效预制体
    @property(Prefab)
    middleTemplate: Prefab = null; // 中间部分的预制体
    @property(Prefab)
    bottomPrefab: Prefab = null; // 底部的预制体

    @property({ type: [TubePart], tooltip: '试管所有可存放小球的部分（栈结构）' })
    parts: TubePart[] = []; // 由底到顶，0为底部

    isCompleted: boolean = false; // 标记试管是否已完成
    
    start() {
        this.corkSprite.enabled = false; // 让木塞Sprite失活
    }

    //clearExistingParts() {
        // 清除现有的中间部分和底部节点
        //this.middleNode.removeAllChildren();
        //this.middleNodes = [];
        //this.bottomNode = null;
    //}

    // 初始化试管的所有部分
    initTubeParts() {
        // 初始化中间部分和底部
        this.parts = [];
        for (let i = 0; i < this.capacity - 1; i++) {
            const middlePart = instantiate(this.middleTemplate).getComponent(TubePart);
            middlePart.node.parent = this.middleNode;
            this.parts.push(middlePart);  // 添加到 parts 数组
        }
        const bottomNode = instantiate(this.bottomPrefab).getComponent(TubePart);
        bottomNode.node.parent = this.middleNode;
        this.parts.push(bottomNode);
    }

    // 点击试管的逻辑
    onClick() {
        if (this.isCompleted) {
            // 如果试管已完成，点击无效
            return;
        }
        //console.log('试管被点击');
        GameManager.getInstance().onTubeClicked(this);
    }

    // 移动小球到试管口
    async moveBallToMouth(balls: Ball[]) {
        //console.log(`移动 ${balls.length} 个小球到试管口`); 
        for (let i = 0; i < balls.length; i++) {
            await new Promise(resolve => setTimeout(resolve, 100 * i)); // 每个小球延迟 0.1 秒
            const ball = balls[i];

            // 获取试管顶部节点的世界坐标
            const topNodeWorldPos = this.topNode.getWorldPosition();
            // 先计算偏移量
            const offset = new Vec3(0, (balls.length - i) * 60 , 0);
            // 加上偏移量得到目标世界坐标
            const targetWorldPos = topNodeWorldPos.add(offset);
            // 将目标世界坐标转换为相对于小球节点的本地坐标
            const offsetPos = new Vec3();
            ball.node.inverseTransformPoint(offsetPos, targetWorldPos);

            console.log(`移动小球 ${i} 到位置 ${offsetPos}`);

            ball.moveTo(offsetPos, 0.7, () => {
                // 动画结束后，清除 TubePart 的引用
                for (let j = 0; j < this.parts.length; j++) {
                    if (this.parts[j].getBall() === ball) {
                        ball.showEffect(); // 显示选中特效
                        this.parts[j].setBall(null);
                        // 先把球挂到 topNode 下
                        ball.node.parent = this.topNode;
                    }
                }
                // 保证球在 topNode 下且位置正确
                this.topNode.addChild(ball.node);
                ball.node.position = offsetPos;
            });
        }
    }

    // 归位完成
    returnComplete() {
        this.isCompleted = true; // 标记试管已完成
        const effectNode = instantiate(this.effectPrefab);
        effectNode.parent = this.node; 
        this.corkSprite.enabled = this.isCompleted;
        //console.log(`试管归位完成，已完成：${this.isCompleted}`);
        // 通知 GameManager 检查是否全部归位
        GameManager.getInstance().checkGameOver();
    }

    // 获取试管顶部的小球
    canAddBall(ball: Ball): boolean {
    const topBall = this.getTopBall();
    return topBall === null || topBall.ballColor === ball.ballColor;
    }

    // 获取试管顶部的小球，如果没有则返回null
    getTopBall(): Ball | null {
    for (let i = this.parts.length - 1; i >= 0; i--) {
        const ball = this.parts[i].getBall();
        if (ball) return ball;
    }
    return null;
    }

    // 存放小球：从底到顶找第一个为空的 TubePart
    addBall(ball: Ball): boolean {
        for (let i = this.parts.length - 1; i >= 0; i--) {
            //console.log(`检查试管的第 ${i} 个部分是否有空位` + this.parts[i].hasBall());
            if (!this.parts[i].hasBall()) {
                //console.log(`将小球 ${ball.ballColor} 添加到试管的第 ${i} 个部分`);
                const targetPart = this.parts[i];
                // 使用 Tool 类方法改变小球父节点，保持世界位置不变
                setParentWithoutChangingWorldPos(ball.node, targetPart.node);
                this.parts[i].setBall(ball);

                ball.moveToWithBounce(new Vec3(0, 0, 0), 0.1, () => {
                    // 设置小球的所属试管
                    ball.hideEffect(); // 隐藏选中特效
                    ball.tube = this; // 更新小球所属试管
                    ball.node.parent = this.parts[i].node;
                    ball.node.position.set(0, 0, 0); // 重置小球位置到试管顶部
                    // 判断是否归位完成
                if (this.checkComplete() && !this.isCompleted) {
                    this.returnComplete();
                }
                });
                return true;
            }
        }
        return false; // 没有空位
    }

    /**
     * 将选中的小球依次放入试管，每个小球间隔 0.5 秒移动
     * @param balls 选中的小球数组
     */
    async addSelectedBalls(balls: Ball[]) {
        for (let i = 0; i < balls.length; i++) {
            const ball = balls[i];
            // 每个小球间隔 0.5 秒
            await new Promise(resolve => setTimeout(resolve, 100));

            // 获取目标试管顶部相对于当前小球所在试管顶部的相对坐标
            const relativePos = getNewParentLocalPosInChild(ball.tube.topNode, this.topNode);
            ball.moveTo(new Vec3(relativePos.x, ball.node.position.y,0), 0.3);

            // 缓动小球的 x 坐标到目标位置
            await new Promise(resolve => {
                tween(ball.node.position)
                   .to(0.3, { x: relativePos.x })
                   .call(() => {
                        if (this.addBall(ball)) {
                            ball.tube = this;
                        }
                        resolve(undefined);
                    })
                   .start();
            });
        }
    }

    // 检查试管是否已满且所有小球颜色相同
checkComplete(): boolean {
    if (this.parts.length === 0) return false;
    let color: BallColor | null = null;
    for (let i = 0; i < this.parts.length; i++) {
        const ball = this.parts[i].getBall();
        if (!ball) return false;
        if (color === null) color = ball.ballColor;
        if (ball.ballColor !== color) return false;
    }
    return true;
}

    // 从试管顶部取出同色小球（只收集，不立即移除）
    removeTopSameColorBalls(): Ball[] {
        const result: Ball[] = [];
        let found = false;
        let targetColor: BallColor | null = null;
        // 从底部（索引0）向上遍历
        for (let i = 0; i < this.parts.length; i++) {
            const ball = this.parts[i].getBall();
            if (!ball) continue;
            if (!found) {
                // 找到第一个有球的TubePart，记录颜色
                targetColor = ball.ballColor;
                found = true;
            }
            if (ball.ballColor === targetColor) {
                result.push(ball);
                //this.parts[i].setBall(null); // 清除该部件的小球引用
            } else {
                break;
            }
        }
        return result;
    }

    /**
     * 获取试管内小球的数量
     * @returns 小球的数量
     */
    getBallCount(): number {
        let count = 0;
        // 遍历所有 TubePart，统计有小球的部件数量
        for (let i = 0; i < this.parts.length; i++) {
            if (this.parts[i].getBall()) {
                count++;
            }
        }
        return count;
    }

    /**
     * 获取试管剩余可存放小球的空间
     * @returns 剩余空间数量
     */
    getEmptySpace(): number {
        // 最大容量减去当前小球数量得到剩余空间
        return this.capacity - 1 - this.getBallCount();
    }
}


